package rerac.components;

import goalie.Component;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import rerac.feature.SentenceFeatureExtractor;
import rerac.protos.Corpus.Document;
import rerac.protos.InstanceCollection.Instance;

/**
 * This extracts features from single sentence documents and writes out 
 * Instances and a FeatureMap in the respective proto format.
 * See rerac.feature.SentenceFeatureExtractor for more details.
 * 
 * @author Benjamin Roth
 *
 */
public class SentenceFeatures implements Component {
  
  public static final String REFERRED_NAME = "sentence_features";

  @Override
  public void cleanup(Map<String, String> outputs) throws IOException {
    File f = new File(outputs.get("output"));
    f.delete();
    f = new File(outputs.get("featuremap"));
    f.delete();
  }

  @Override
  public Map<String, String> run(Map<String, String> params) throws IOException {
    String inputFN = params.get("input");
    String outputFN = params.containsKey("output_destination") ?
        params.get("output_destination") : inputFN + ".feats";
    String featureMapFN = params.containsKey("featuremap_destination") ?
            params.get("featuremap_destination") : inputFN + ".featmap";
    int maxEntries = Integer.MAX_VALUE;
    if (params.containsKey("max_entries")) {
      maxEntries = Integer.parseInt(params.get("max_entries"));
    }
    boolean useHash = params.containsKey("use_hash") ?
        Boolean.parseBoolean(params.get("use_hash")) : false;
        
    BufferedInputStream is = new BufferedInputStream(new FileInputStream(
        inputFN));
    DataOutputStream instanceOut = new DataOutputStream(
        new BufferedOutputStream(new FileOutputStream(outputFN)));

    SentenceFeatureExtractor extractor = new SentenceFeatureExtractor(useHash);
    int numEntries = 0;
    for (Document doc;
         numEntries < maxEntries && 
         (doc = Document.parseDelimitedFrom(is)) != null;) {
      for (Instance inst : extractor.extract(doc)) {
        inst.writeDelimitedTo(instanceOut);
        ++numEntries;
      }
    }
    instanceOut.close();
    is.close();
    
    DataOutputStream featureMapOut = new DataOutputStream(
        new BufferedOutputStream(new FileOutputStream(featureMapFN)));
    extractor.getFeatureMap().writeDelimitedTo(featureMapOut);
    featureMapOut.close();
    Map<String, String> outMap = new HashMap<String, String>();
    outMap.put("output", outputFN);
    outMap.put("featuremap", featureMapFN);
    return outMap;
  }
}
